/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.yanlight.Constants;

/**
 * 
 *
 * @author haolw
 * @time 2017/06/28
 */
public abstract class WebUtil {
	private static String CHARSET = Constants.DEFAULT_CHARSET_NAME;

	public static Boolean apiRequest() {
		return apiRequest(getRequest());
	}

	public static Boolean apiRequest(HttpServletRequest request) {
		if (ajax(request)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断请求是否是ajax
	 * 
	 * @param request
	 * @return
	 */
	public static Boolean ajax(HttpServletRequest request) {
		String requestType = request.getHeader("X-Requested-With");
		if (null != requestType && "XMLHttpRequest".equals(requestType)) {
			return true;
		}
		return false;
	}

	/**
	 * 得到客户端请求ip
	 * 
	 * @param request
	 * @return
	 */
	public static String getRequestIp(HttpServletRequest request) {
		String result = "";
		String heads[] = { "x-forwarded-for", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP",
				"HTTP_X_FORWARDED_FOR" };
		for (String head : heads) {
			if (isEmpty(result) || "unknown".equalsIgnoreCase(result)) {
				result = request.getHeader(head);
			}
		}
		if (!isEmpty(result)) {
			if (result.indexOf(".") != -1) {
				Pattern pattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
				Matcher matcher = pattern.matcher(result);
				result = null;
				while (matcher.find()) {
					result = matcher.group(0);
					break;
				}
			} else {
				result = null;
			}

		}
		if (isEmpty(result) || "unknown".equalsIgnoreCase(result)) {
			result = request.getRemoteAddr();
		}
		return result;
	}

	/**
	 * 
	 * @param response
	 * @param content
	 */
	public static void renderText(HttpServletResponse response, String content) {
		render(response, content, "Content-Type", "text/html;charset=" + CHARSET);
	}

	/**
	 * 
	 * @param response
	 * @param obj
	 */
	public static void renderJson(HttpServletResponse response, Object obj) {
		renderJson(response, obj, CHARSET);
	}
	
	/**
	 * 
	 * @param response
	 * @param content
	 */
	public static void renderJson(HttpServletResponse response, String content) {
		renderJson(response, content, CHARSET);
	}

	/**
	 * 
	 * @param response
	 * @param data
	 * @param charset
	 */
	public static void renderJson(HttpServletResponse response, Object data, String charset) {
		try {
			render(response, JsonUtil.toJson(data), "Content-Type", "text/json;charset=" + CHARSET);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 
	 * @param response
	 * @param content
	 * @param charset
	 */
	public static void renderJson(HttpServletResponse response, String content, String charset) {
		try {
			render(response, content, "Content-Type", "text/json;charset=" + CHARSET);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 
	 * @param response
	 * @param content
	 * @param headerName
	 * @param headerValue
	 */
	public static void render(HttpServletResponse response, String content, String headerName, String headerValue) {
		response.addHeader(headerName, headerValue);
		response.setStatus(200);
		render(response, content);
	}

	/**
	 * 
	 * @param response
	 * @param content
	 */
	private static void render(HttpServletResponse response, String content) {
		try {
			PrintWriter pw = response.getWriter();
			pw.write(content);
			pw.flush();
			pw.close();
			return;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取request中的报文体
	 * 
	 * @return
	 */
	public static String getRequestBody() {
		return getRequestBody(getRequest());
	}

	/**
	 * 获取request中的报文体
	 * 
	 * @param request
	 * @return
	 */
	public static String getRequestBody(HttpServletRequest request) {
		String result = "";
		try {
			BufferedReader reader = request.getReader();
			result = copyToString(reader);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
		return result;
	}

	/**
	 * 
	 * @param query
	 * @return
	 */
	public static Map<String, String> decodeUrlQuery(String query) {
		Map<String, String> result = new HashMap<String, String>();
		String[] pairs = query.split("&");
		if (pairs != null && pairs.length > 0) {
			for (String pair : pairs) {
				String[] param = pair.split("=", 2);
				if (param != null && param.length == 2) {
					result.put(param[0], param[1]);
				}
			}
		}
		return result;
	}

	/**
	 * 使用默认的UTF-8字符集编码请求参数值。
	 * 
	 * @param value
	 *            参数值
	 * @return 编码后的参数值
	 */
	public static String urlEncode(String value) {
		return urlEncode(value, CHARSET);
	}

	/**
	 * 使用指定的字符集编码请求参数值。
	 * 
	 * @param value
	 *            参数值
	 * @param charset
	 *            字符集
	 * @return 编码后的参数值
	 */
	public static String urlEncode(String value, String charset) {
		String result = null;
		if (!isEmpty(value)) {
			try {
				result = URLEncoder.encode(value, charset);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return result;
	}

	/**
	 * 
	 * @return
	 */
	public static HttpServletRequest getRequest() {
		return getRequestAttributes().getRequest();
	}

	/**
	 * 
	 * @return
	 */
	public static HttpServletResponse getResponse() {
		return getRequestAttributes().getResponse();
	}

	/**
	 * 
	 * @return
	 */
	public static HttpSession getSession() {
		HttpServletRequest request = getRequest();
		if (request == null) {
			return null;
		}
		return request.getSession();
	}

	/**
	 * 
	 * @return
	 */
	private static ServletRequestAttributes getRequestAttributes() {
		return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
	}

	/**
	 * 判断是否空
	 * 
	 * @param cs
	 * @return
	 */
	private static boolean isEmpty(CharSequence cs) {
		return cs == null || cs.length() == 0;
	}

	private static String copyToString(Reader in) throws IOException {
		StringWriter out = new StringWriter();
		copy(in, out);
		return out.toString();
	}

	private static int copy(Reader in, Writer out) throws IOException {
		try {
			int byteCount = 0;
			char[] buffer = new char[4096];
			int bytesRead = -1;
			while ((bytesRead = in.read(buffer)) != -1) {
				out.write(buffer, 0, bytesRead);
				byteCount += bytesRead;
			}
			out.flush();
			return byteCount;
		} finally {
			try {
				in.close();
			} catch (IOException ex) {
			}
			try {
				out.close();
			} catch (IOException ex) {
			}
		}
	}
}
